package controllers

import (
	"bluebell6/dao/mysql"
	"bluebell6/logic"
	"bluebell6/models"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
)

// 代码的处理过程首先SignUpHandler接受前端传回来的数据
// 1.获取参数和参数的校验(要反序列化)我们还定义采用统一的错误响应方式还定义返回前端的函数使返回信息更加清晰
// 2.业务处理放到logic层去处理(判断用户是否存在(这个在dao层),不存在用雪花算法生成uid然后保存到mysql中)
// SignUpHandler处理注册请求的函数
func SignUpHandler(c *gin.Context) {
	//1.获取参数和参数校验
	p := new(models.ParamSignUp)
	if err := c.ShouldBindJSON(p); err != nil {
		//请求参数有误,直接返回响应
		zap.L().Error("SignUp with invalid param", zap.Error(err))
		//判断err是不是validator.validationErrors类型,这个这个类型才可以进行翻译
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(c, CodeInvalidParsm)
			return
		}
		//是的话就可以进行翻译验证错误信息翻译成指定语言
		ResponseErrorWithMsg(c, CodeInvalidParsm, removeTopStruct(errs.Translate(trans)))
		return
	}
	////手动对请求参数进行详细的业务规则校验
	//if len(p.Username) == 0 || len(p.Password) == 0 || len(p.RePassword) == 0 || p.Password != p.RePassword {
	//	zap.L().Error("SignUp with invalid param")
	//	c.JSON(http.StatusOK, gin.H{
	//		"msg": "请求参数有误",
	//	})
	//	return
	//}
	//请求参数有误,返回响应
	fmt.Println(p)
	//2.业务处理
	if err := logic.SignUp(p); err != nil {
		zap.L().Error("logic.SignUp failed", zap.Error(err))
		if errors.Is(err, mysql.ErrorUserExist) {
			ResponseError(c, CodeUserExist)
			return
		}
		ResponseError(c, CodeServerBusy)
		return
	}
	//3.返回响应
	ResponseSuccess(c, nil)
}

// LoginHandler处理登录的函数
func LoginHandler(c *gin.Context) {
	//1.获取请求参数及参数校验
	p := new(models.ParamLogin)
	if err := c.ShouldBindJSON(p); err != nil {
		zap.L().Error("LoginUp with invalid param", zap.Error(err))
		//判断err是不是validator.validationErrors类型,这个这个类型才可以进行翻译
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(c, CodeInvalidParsm)
			return
		}
		//是的话就可以进行翻译
		ResponseErrorWithMsg(c, CodeInvalidParsm, removeTopStruct(errs.Translate(trans)))
		return
	}
	//2.业务逻辑处理
	user, err := logic.Login(p)
	if err != nil {
		zap.L().Error("Login error", zap.String("username", p.Username), zap.Error(err))
		if errors.Is(err, mysql.ErrorUserNotExist) {
			ResponseError(c, CodeUserNotExist)
			return
		}
		ResponseError(c, CodeInvalidPassword)
		return
	}
	//3.返回响应
	ResponseSuccess(c, gin.H{
		"user_id":   fmt.Sprintf("%d", user.UserID), //id值大于1<<53-1,int64类型的最大值是1<<63-1
		"user_name": user.Username,
		"token":     user.Token,
	})
}
